<?php
/**
 * This is the model class for table "{{address}}".
 *
 * The followings are the available columns in table '{{address}}':
 * @property integer $id
 * @property string $module
 * @property integer $module_id
 * @property integer $is_default
 * @property string $building_name
 * @property string $address
 * @property string $street
 * @property string $district
 * @property string $city
 * @property string $province
 * @property string $type_number
 * @property string $locality
 * @property string $state
 * @property string $postal_code
 * @property string $country_code
 * @property string $formatted_address
 * @property float $latitude
 * @property float $longitude
 * @property integer $status_code
 * @property string $create_timezone
 * @property string $create_timestamp
 * @property string $create_datetime
 * @property string $create_date
 * @property string $create_time
 * @property integer $create_by
 * @property string $update_timezone
 * @property string $update_timestamp
 * @property string $update_datetime
 * @property string $update_date
 * @property string $update_time
 * @property integer $update_by
 */
class Address extends ActiveRecord {

    public $moduleId_;
    public $module_;
    public $status_;
    
    public $buildingName_;
    public $address_;
    public $street_;
    public $district_; // city area/ district
    public $city_; // city/ town/ village
    public $province_;
    public $typeNumber_; // p.o. box
    public $locality_;
    public $state_;
    public $postalCode_;
    public $country_;
    
    public $latitude_;
    public $longitude_;

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Address the static model class
     */
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
        return '{{address}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('moduleId_, module_, country_', 'filter', 'filter'=>'trim'),
            //array('buildingName_, address_, street_, district_, city_, province_, typeNumber_, locality_, state_, postalCode_','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),
            array('buildingName_, address_, street_, district_, city_, province_, typeNumber_, locality_, state_, postalCode_', 'filter', 'filter'=>array($this, 'filterTrimComma')),
            array('address_, street_, district_, city_, province_, locality_, state_','filter','filter'=>array($this, 'filterFormat')),
            
            array('module_', 'required', 'on'=>'insert'),
            array('module_', 'length', 'max'=>45),
            array('moduleId_', 'numerical', 'allowEmpty'=>false, 'integerOnly'=>true, 'on'=>'insert'),
            
            // common rules
            array('buildingName_, street_, district_, city_, province_, locality_, state_', 'length', 'max'=>255),
            array('address_', 'length', 'max'=>300),
            array('typeNumber_', 'length', 'max'=>45),
            array('postalCode_', 'length', 'max'=>10),
            array('country_', 'required', 'on'=>'insert'),
            array('country_', 'length', 'max'=>3),
            array('country_', 'in', 'range'=>array_keys($this->countryOption)),
            array('latitude_, longitude_', 'numerical'),
            array('buildingName_, address_, street_, district_, city_, province_, locality_, state_', 'ext.validators.AddressFormatValidator'),
            array('moduleId_, module_, buildingName_, address_, street_, district_, city_, province_, typeNumber_, locality_, state_, postalCode_, country_, latitude_, longitude_', 'safe', 'on'=>'insert, update'),

        );
    }

    public function filterTrimComma($value){
        return trim($value,' ,.');
    }
    
    public function filterFormat($value){
        return ucwords(strtolower($value));
    }
    
    /**
     * @return array relational rules.
     */
    public function relations() {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            // must included
            'creator' => array(self::BELONGS_TO, 'User', 'create_by'),
            'editor' => array(self::BELONGS_TO, 'User', 'update_by'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
        return array(
            'buildingName_'=>Lang::t('address.lbl.building.name'),
            'address_'=>Lang::t('address.lbl.address'),
            'street_'=>Lang::t('address.lbl.street'),
            'district_'=>Lang::t('address.lbl.district'),
            'city_'=>Lang::t('address.lbl.city'),
            'province_'=>Lang::t('address.lbl.province'),
            'typeNumber_'=>Lang::t('address.lbl.type.number'),
            'locality_'=>Lang::t('address.lbl.locality'),
            'state_'=>Lang::t('address.lbl.state'),
            'postalCode_'=>Lang::t('address.lbl.postal.code'),
            'country_'=>Lang::t('address.lbl.country'),
            'latitude_'=>Lang::t('address.lbl.latitude'),
            'longitude_'=>Lang::t('address.lbl.longitude'),
        );
    }

    /**
     * scopes
     */
    public function scopes() {
        $t = $this->getTableAlias(false);
        return array(
            'primary' => array(
                'condition' => implode(' AND ', array(
                    $t.'.is_default=true',
                )),
            ),
            'published' => array(
                'condition' => $t.'.status_code = :activeStatus'.$t,
                'params' => array(
                    ':activeStatus'.$t => Option::STATUS_ACTIVE,
                ),
            ),
            'accessible'=>array(
                'condition' => $t.'.status_code <> :deletedStatus'.$t,
                'params' => array(
                    ':deletedStatus'.$t => Option::STATUS_DELETED,
                ),
            ),
        );
    }

    public function module($module = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t . '.module=:module'.$t,
            'params' => array(
                ':module'.$t => strtolower($module),
            ),
        ));
        return $this;
    }

    public function moduleId($id = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t.'.module_id=:moduleId'.$t,
            'params' => array(
                ':moduleId'.$t => (int)$id,
            ),
        ));
        return $this;
    }
    
    public function countrySearch($id = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t.'.country_code=:moduleId'.$t,
            'params' => array(
                ':moduleId'.$t => (int)$id,
            ),
        ));
        return $this;
    }
    
    public function autoFill(&$model=null){
        if($this->isNewRecord){
            $this->module_=get_class($model);
            $this->moduleId_=0;
            $this->country_=Yii::app()->controller->countryCode;
        }else{
            $this->buildingName_=$this->buildingName;
            $this->address_ = $this->address;
            $this->street_ = $this->street;
            $this->district_ = $this->district;
            $this->city_ = $this->city;
            $this->province_ = $this->province;
            $this->typeNumber_ = $this->typeNumber;
            $this->locality_ = $this->locality;
            $this->state_ = $this->state;
            $this->postalCode_ = $this->postalCode;
            $this->country_ = $this->countryCode;
            $this->latitude_=$this->latitude;
            $this->longitude_=$this->longitude;
        }
    }
    
    public function getCountryOption($id = null) {
        return Option::country($id);
    }
    
    public function getIsEmptyInput(){
        return !count(array_filter(array(
            $this->buildingName_,
            $this->address_,
            $this->street_,
            $this->locality_,
            $this->district_,
            $this->city_,
            $this->province_,
            $this->typeNumber_,
            $this->state_,
            $this->postalCode_,
            $this->country_,
            $this->latitude_,
            $this->longitude_,
        )));
    }
    
    protected function beforeSave(){
        if(parent::beforeSave()){
            
            if(Yii::app()->params['geocoderMode']){
                $geo=new Geocoder();
                $geo->address=implode(',',array_filter(array(
                    $this->buildingName_,
                    $this->address_,
                    $this->street_,
                    $this->locality_,
                    $this->district_,
                    $this->city_,
                    $this->province_,
                    $this->typeNumber_,
                    $this->postalCode_,
                    $this->state_,
                    $this->country_,
                )));
                $geo->components='country:'.$this->country_;
                $geo->getResponse();
                if(empty($this->locality_)) $this->locality_=$geo->get(Geocoder::SUBLOCALITY);
                if(empty($this->city_)) $this->city_=$geo->get(Geocoder::LOCALITY);
                if(empty($this->state_)) $this->state_=$geo->get(Geocoder::STATE);
                if(empty($this->postalCode_)) $this->postalCode_=$geo->get(Geocoder::POSTAL_CODE);
                $this->formatted_address=$geo->get(Geocoder::FORMATTED_ADDRESS);
                if(empty($this->latitude_)) $this->latitude_=$geo->get(Geocoder::LATITUDE);
                if(empty($this->longitude_)) $this->longitude_=$geo->get(Geocoder::LONGITUDE);
            }
            $this->building_name=$this->buildingName_;
            $this->address=$this->address_;
            $this->street=$this->street_;
            $this->locality=$this->locality_;
            $this->district=$this->district_;
            $this->city=$this->city_;
            $this->province=$this->province_;
            $this->type_number=$this->typeNumber_;
            $this->state=$this->state_;
            $this->postal_code=$this->postalCode_;
            $this->country_code=$this->country_;
            $this->latitude=$this->latitude_;
            $this->longitude=$this->longitude_;
            
            if ($this->isNewRecord) {
                $this->module_id=(int)$this->moduleId_;
                $this->module=strtolower($this->module_);
                $this->is_default=true;
                $this->status_code=Option::STATUS_ACTIVE;
                
                $this->setCreateDateTime();
            } else {
                $this->setUpdateDateTime();
            }
            return true;
        }else
            return false;
    }

    protected function afterSave() {
        parent::afterSave();
        $this->setDefault($this->module_, $this->moduleId_);
    }
    
    public function setDefault(&$module, &$moduleId, $id=null){
        $model=$this->primary()->accessible()->module($module)->moduleId($moduleId)->find();
        if($model && $id){
            $newDefault=$this->accessible()->module($module)->moduleId($moduleId)->findByPk((int)$id);
            if($newDefault->saveAttributes(array('is_default'=>true))){
                $model->saveAttributes(array('is_default'=>false));
            }
        }elseif(empty($model) && empty($id)){
            $model=$this->accessible()->module($module)->moduleId($moduleId)->find();
            if(!empty($model))
                $model->saveAttributes(array('is_default'=>true));
        }
    }
    
    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function subQuery(){
        $criteria = new CDbCriteria;
        $criteria->alias=$t=strtolower(get_class($this));
        $criteria->select=array($t.'.module_id');
        $criteria->distinct=true;
        
        $criteria->compare($t.'.module', strtolower($this->module_));
        $criteria->compare($t.'.country_code', $this->country_);
        
        return $this->criteriaToSQL($this, $criteria);
    }
    
    
    public function search() {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;

        return new ActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }
    
    public function getFullAddress() {
        return implode(', ', array_unique(array_filter(array(
            $this->building_name,
            $this->address,
            $this->street,
            $this->locality,
            $this->typeNumber,
            $this->postal_code,
            $this->district,
            $this->city,
            $this->province,
            $this->state,
            $this->country,
        ))));
    }

    public function getBuildingName(){
        return $this->building_name;
    }
    
    public function getTypeNumber() {
        return $this->type_number;
    }

    public function getPostalCode() {
        return $this->postal_code;
    }

    public function getCountryCode() {
        return empty($this->country_code)? Yii::app()->controller->countryCode:$this->country_code;
    }

    public function getCountry() {
        return Option::country($this->country_code);
    }

}//end class